--check /shop/spider

local IP_RF_30_KEY_PRE="SPIDER_IP_RF_30_"
-- 同一IP且（没有Referer或Referer相同（不包括参数）），30秒内访问 >= 2次
local IP_RF_30_VAL_MAX=2
local IP_RF_30_TYPE='a'

local IP_RF_300_KEY_PRE="SPIDER_IP_RF_300_"
-- 同一IP且（没有Referer或Referer相同（不包括参数）），300秒内访问 >= 5次
local IP_RF_300_VAL_MAX=5
local IP_RF_300_TYPE='b'

local IP_1_KEY_PRE="SPIDER_IP_1_"
-- 同一IP，1秒内访问 >= 2次
local IP_1_VAL_MAX=2
local IP_1_TYPE='c'

local IP_5_KEY_PRE="SPIDER_IP_5_"
-- 同一IP，5秒内访问 >= 5次
local IP_5_VAL_MAX=5
local IP_5_TYPE='d'

local IP_30_KEY_PRE="SPIDER_IP_30_"
-- 同一IP，30秒内访问 >= 10次
local IP_30_VAL_MAX=10
local IP_30_TYPE='e'

local IP_300_KEY_PRE="SPIDER_IP_300_"
-- 同一IP，300秒内访问 >= 30次
local IP_300_VAL_MAX=30
local IP_300_TYPE='f'

local CK_1_KEY_PRE="SPIDER_CK_1_"
-- 同一Cookie，1秒内访问 >= 2次
local CK_1_VAL_MAX=2
local CK_1_TYPE='g'

local CK_5_KEY_PRE="SPIDER_CK_5_"
-- 同一Cookie，5秒内访问 >= 5次
local CK_5_VAL_MAX=5
local CK_5_TYPE='h'

local CK_30_KEY_PRE="SPIDER_CK_30_"
-- 同一Cookie，30秒内访问 >= 10次
local CK_30_VAL_MAX=10
local CK_30_TYPE='i'

local CK_300_KEY_PRE="SPIDER_CK_300_"
-- 同一Cookie，300秒内访问 >= 30次
local CK_300_VAL_MAX=30
local CK_300_TYPE='j'



local headers = ngx.req.get_headers()
local client_ip = headers["X-FORWARDED-FOR"] or ngx.var.remote_addr or headers["X-REAL-IP"]
local referer = headers["referer"]
-- local cookie = headers["cookie"]
-- local user_agent = headers["user-agent"]
local session_id = ngx.var.cookie_JSESSIONID
local request_uri = ngx.var.request_uri;

if referer then
   local referer_pos = string.find(referer,'?')
   if referer_pos then
      referer = string.sub(referer, 1, referer_pos-1)
   end
else
   referer = ''
end

--ngx.say("client_id:",client_ip)
--ngx.say("referer:",referer)
--ngx.say("cookie::",cookie)
--ngx.say("user_agent:",user_agent)
--ngx.say("session_id:",session_id)

-- get redis connect
local redis = require("resty.redis")
local red = redis:new()
red:set_timeout(2000)   
--local ok,err = red:connect("192.168.201.163",6379)
local ok,err = red:connect("r-bp1e00pxqe5bvlxa6o.redis.rds.aliyuncs.com",6379)
if not ok then
   ngx.say("connect redis failed:",err)
end
--local res,err = red:auth("xpNsEz7Pvn7h0QoM")
local res,err = red:auth("3DqbSHXePBUN9D5yuJgX")
if not res then
   ngx.say("failed to authenticate: ",err)
end

local is_spider = false
local spider_type=''


local ip_rf_30_key = IP_RF_30_KEY_PRE .. client_ip .. "_" .. referer
--ngx.say("<br/>ip_rf_30_key:",ip_rf_30_key)
local rsp,err = red:incr(ip_rf_30_key)
--ngx.say("<br/>ip_rf_30 curr count:",rsp)
if rsp == 1 then
   red:expire(ip_rf_30_key,30)
elseif rsp >= IP_RF_30_VAL_MAX then
   is_spider = true
   spider_type = IP_RF_30_TYPE..','..spider_type
   --ngx.say("<br/>ip_rf_30 spider call")
end

local ip_rf_300_key = IP_RF_300_KEY_PRE .. client_ip .. "_" .. referer
--ngx.say("<br/>ip_rf_300_key:",ip_rf_300_key)
local rsp,err = red:incr(ip_rf_300_key)
--ngx.say("<br/>ip_rf_300 curr count:",rsp)
if rsp == 1 then
   red:expire(ip_rf_300_key,300)
elseif rsp >= IP_RF_300_VAL_MAX then
   is_spider = true
   spider_type =IP_RF_300_TYPE ..','.. spider_type
   --ngx.say("<br/>ip_rf_300 spider call")
end

local ip_1_key = IP_1_KEY_PRE .. client_ip
--ngx.say("<br/>ip_1_key:",ip_1_key)
local rsp,err = red:incr(ip_1_key)
--ngx.say("<br/>ip_1 curr count:",rsp)
if rsp == 1 then
   red:expire(ip_1_key,1)
elseif rsp >= IP_1_VAL_MAX then
   is_spider = true
   spider_type = IP_1_TYPE ..','.. spider_type
   --ngx.say("<br/>ip_1 spider call")
end

local ip_5_key = IP_5_KEY_PRE .. client_ip
--ngx.say("<br/>ip_5_key:",ip_5_key)
local rsp,err = red:incr(ip_5_key)
--ngx.say("<br/>ip5 curr count:",rsp)
if rsp == 1 then
   red:expire(ip_5_key,5)
elseif rsp >= IP_5_VAL_MAX then
   is_spider = true
   spider_type = IP_5_TYPE..','..spider_type
   --ngx.say("<br/>ip_5 spider call")
end

local ip_30_key = IP_30_KEY_PRE .. client_ip
--ngx.say("<br/>ip_30_key:",ip_30_key)
local rsp,err = red:incr(ip_30_key)
--ngx.say("<br/>ip_30 curr count:",rsp)
if rsp == 1 then
   red:expire(ip_30_key,30)
elseif rsp >= IP_30_VAL_MAX then
   is_spider = true
   spider_type = IP_30_TYPE ..','.. spider_type
  --ngx.say("<br/>ip_30 spider call")
end

local ip_300_key = IP_300_KEY_PRE .. client_ip
--ngx.say("<br/>ip_300_key:",ip_300_key)
local rsp,err = red:incr(ip_300_key)
--ngx.say("<br/>ip_300 curr count:",rsp)
if rsp == 1 then
   red:expire(ip_300_key,300)
elseif rsp >= IP_300_VAL_MAX then
   is_spider = true
   spider_type = IP_300_TYPE ..','.. spider_type
   --ngx.say("<br/>ip_300 spider call")
end


-- cookie 维度反爬
if session_id then
    local ck_1_key = CK_1_KEY_PRE .. session_id
    --ngx.say("<br/>ck_1_key:",ck_1_key)
    local rsp,err = red:incr(ck_1_key)
    --ngx.say("<br/>ck_1 curr count:",rsp)
    if rsp == 1 then
       red:expire(ck_1_key,1)
    elseif rsp >= CK_1_VAL_MAX then
       is_spider = true
       spider_type = CK_1_TYPE ..','.. spider_type
       --ngx.say("<br/>ck_1 spider call")
    end

    local ck_5_key = CK_5_KEY_PRE .. session_id
    --ngx.say("<br/>ck_5_key:",ck_5_key)
    local rsp,err = red:incr(ck_5_key)
    --ngx.say("<br/>ck_5 curr count:",rsp)
    if rsp == 1 then
       red:expire(ck_5_key,5)
    elseif rsp >= CK_5_VAL_MAX  then
       is_spider = true
       spider_type = CK_5_TYPE ..','.. spider_type
       --ngx.say("<br/>ck_5 spider call")
    end

    local ck_30_key = CK_30_KEY_PRE .. session_id
    --ngx.say("<br/>ck_30_key:",ck_30_key)
    local rsp,err = red:incr(ck_30_key)
    --ngx.say("<br/>ck_30 curr count:",rsp)
    if rsp == 1 then
       red:expire(ck_30_key,30)
    elseif rsp >= CK_30_VAL_MAX then
       is_spider = true
       spider_type = CK_30_TYPE..','..spider_type
       --ngx.say("<br/>ck_30 spider call")
    end

    local ck_300_key = CK_300_KEY_PRE .. session_id
    --ngx.say("<br/>ck_300_key:",ck_300_key)
    local rsp,err = red:incr(ck_300_key)
    --ngx.say("<br/>ck_300 curr count:",rsp)
    if rsp == 1 then
       red:expire(ck_300_key,300)
    elseif rsp >= CK_300_VAL_MAX then
       is_spider = true
       spider_type = CK_300_TYPE ..','.. spider_type
       --ngx.say("<br/>ck_300 spider call")
    end
end

-- releas redis connect
local ok,err = red:set_keepalive(10000,200)
if not ok then
   ngx.say("set keepalive error : ",err)
end

if is_spider then

    --local pos = string.find(request_uri,'?')
    --if pos then
        --request_uri = request_uri .. "&spider=1"
    --else
        --request_uri = request_uri .. "?spider=1"
    --end
    --ngx.say("request_uri===",request_uri)
    --local args = ngx.req.get_uri_args()
    --args["q"]=1
    --ngx.req.set_uri_args(args)
    --ngx.req.set_uri(request_uri,false)
    local args = ngx.req.get_uri_args()
    --ngx.say("args===",args["a"])
    args["spider"] = 1
    args["spiderType"] = spider_type
    ngx.req.set_uri_args(args)
end
--return ngx.exit(ngx.HTTP_OK)



